package scatter.comment.rest.rate.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.Assert;
import scatter.comment.pojo.rate.param.CommentRateAddRateParam;
import scatter.comment.pojo.rate.param.CommentRateCancelRateParam;
import scatter.comment.pojo.rate.po.CommentRate;
import scatter.comment.pojo.rate.po.CommentRate;
import scatter.comment.rest.componentext.CommentRateOnAddOrCancelListener;
import scatter.comment.rest.rate.mapstruct.CommentRateMapStruct;
import scatter.comment.rest.rate.mapper.CommentRateMapper;
import scatter.comment.rest.rate.service.ICommentRateService;
import scatter.common.pojo.form.BasePageQueryForm;
import scatter.common.rest.service.IBaseAddUpdateQueryFormServiceImpl;
import org.springframework.stereotype.Service;
import scatter.comment.pojo.rate.form.CommentRateAddForm;
import scatter.comment.pojo.rate.form.CommentRateUpdateForm;
import scatter.comment.pojo.rate.form.CommentRatePageQueryForm;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * <p>
 * 评分表 服务实现类
 * </p>
 *
 * @author yw
 * @since 2021-11-03
 */
@Slf4j
@Service
@Transactional
public class CommentRateServiceImpl extends IBaseAddUpdateQueryFormServiceImpl<CommentRateMapper, CommentRate, CommentRateAddForm, CommentRateUpdateForm, CommentRatePageQueryForm> implements ICommentRateService {
    
    @Qualifier("commonDbTaskExecutor")
    @Autowired
    private ExecutorService executorService;

    @Autowired(required = false)
    private List<CommentRateOnAddOrCancelListener> commentRateOnAddOrCancelListenerList;

    @Override
    public void preAdd(CommentRateAddForm addForm,CommentRate po) {
        super.preAdd(addForm,po);

    }

    @Override
    public void preUpdate(CommentRateUpdateForm updateForm,CommentRate po) {
        super.preUpdate(updateForm,po);

    }



    /**
     * 异步处理添加，该方法永远返回true
     * @param addRatetParam
     * @return
     */
    @Override
    public CommentRate addRate(CommentRateAddRateParam addRatetParam) {
        CommentRate commentSubjectRate = CommentRateMapStruct.INSTANCE.addRatetParamToPo(addRatetParam);
        commentSubjectRate.setTimeAt(LocalDateTime.now());
        // 楼层默认设置为1
        commentSubjectRate.setFloor(Optional.ofNullable(addRatetParam.getFloor()).orElse(1));
        log.info("开始添加一个评分,subjectId={},userId={}",addRatetParam.getSubjectId(),addRatetParam.getOwnerUserId());
        boolean save = save(commentSubjectRate);
        log.info("添加一个评分结束,subjectId={},userId={},id={}",addRatetParam.getSubjectId(),addRatetParam.getOwnerUserId(),commentSubjectRate.getId());
        if (!isEmpty(commentRateOnAddOrCancelListenerList)) {
            for (CommentRateOnAddOrCancelListener commentRateOnAddListener : commentRateOnAddOrCancelListenerList) {
                commentRateOnAddListener.onCommentRateAdd(addRatetParam,commentSubjectRate);
            }
        }
        return commentSubjectRate;
    }

    /**
     * 异步处理取消，该方法永远返回 true
     * @param cancelRateParam
     * @return
     */
    @Override
    public boolean cancelRate(CommentRateCancelRateParam cancelRateParam) {
        executorService.execute(()->{
            log.info("开始取消评分,subjectId={},userId={}",cancelRateParam.getSubjectId(),cancelRateParam.getOwnerUserId());
            LambdaQueryWrapper<CommentRate> rateLambdaQueryWrapper = Wrappers.<CommentRate>lambdaQuery()
                    .eq(CommentRate::getSubjectId, cancelRateParam.getSubjectId())
                    .eq(CommentRate::getOwnerUserId, cancelRateParam.getOwnerUserId())
                    .eq(!isStrEmpty(cancelRateParam.getGroupFlag()), CommentRate::getGroupFlag, cancelRateParam.getGroupFlag() );

            CommentRate one = getOne(rateLambdaQueryWrapper);
            if (one == null) {
                log.error("取消评分，未获取到评分数据，直接返回");
                return;
            }

            boolean remove = removeById(one.getId());

            if (!isEmpty(commentRateOnAddOrCancelListenerList)) {
                for (CommentRateOnAddOrCancelListener commentRateOnAddListener : commentRateOnAddOrCancelListenerList) {
                    commentRateOnAddListener.onCommentRateCancel(cancelRateParam,one);
                }
            }

            log.info("取消评分结束,subjectId={},userId={}",cancelRateParam.getSubjectId(),cancelRateParam.getOwnerUserId());
        });
        return true;
    }

    @Override
    public Map<String, Page<CommentRate>> listLatestRateForPerSubject(List<String> subjectIds, Integer count, String groupFlag) {
        Assert.notEmpty(subjectIds,"subjectIds 不能为空");
        Assert.notNull(count,"count 不能为空");


        Map<String,Page<CommentRate>> result = new HashMap<>();

        CompletableFuture[] completableFutures = subjectIds.stream().map(subjectId -> CompletableFuture.supplyAsync(() -> {
            // 我嚓，这个 page 不能提出来，否则得到的数据会是一样的
            Page page = convertPage(new BasePageQueryForm().setCurrent(1L).setSize(Integer.toUnsignedLong(count)));
            page.setSearchCount(false);
            Page page1 = page(page, Wrappers.<CommentRate>lambdaQuery()
                    .eq(CommentRate::getSubjectId, subjectId)
                    .eq(!isStrEmpty(groupFlag), CommentRate::getGroupFlag, groupFlag)
                    .orderByDesc(CommentRate::getTimeAt));
            return page1;
        }, executorService).whenComplete((r,e)->{result.put(subjectId, (Page<CommentRate>)r);})).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(completableFutures).join();
        return result;
    }

}
